/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2024-11-30     huanf       the first version
 */

#include <rtthread.h>
#include <board.h>
#include <drv_common.h>

// 定义 I²S 句柄
I2S_HandleTypeDef hi2s3;
DMA_HandleTypeDef hdma_spi3_tx;


void HAL_I2S_MspInit(I2S_HandleTypeDef* hi2s)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    if (hi2s->Instance == SPI3)  // 判断是否为 SPI3（I²S3）
    {
        // 1. 启用 SPI3 时钟
        __HAL_RCC_SPI3_CLK_ENABLE();

        // 2. 启用 GPIO 时钟（PA15、PB3、PB5 对应 I²S3 引脚）
        __HAL_RCC_GPIOA_CLK_ENABLE();
        __HAL_RCC_GPIOB_CLK_ENABLE();
        __HAL_RCC_AFIO_CLK_ENABLE();

        __HAL_AFIO_REMAP_SWJ_NOJTAG();

        // 3. 配置 GPIO 引脚
        // 配置 I²S3_WS (LRCK) 引脚 -> PA15
        GPIO_InitStruct.Pin = GPIO_PIN_15;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;  // 复用推挽模式
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

        // 配置 I²S3_SCK (BCLK) 引脚 -> PB3
        GPIO_InitStruct.Pin = GPIO_PIN_3;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;  // 复用推挽模式
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
        HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

        // 配置 I²S3_SD (DATA) 引脚 -> PB5
        GPIO_InitStruct.Pin = GPIO_PIN_5;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;  // 复用推挽模式
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
        HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

        // 如果需要 MCLK 输出，请在此启用并配置相应引脚（STM32F1 不支持 MCLK，跳过）

        // 4. 如果使用 DMA，则在此初始化 DMA
        // 可选：初始化 SPI3 的 DMA 通道（TX）
        __HAL_RCC_DMA2_CLK_ENABLE();

        // 配置 DMA 通道
        hdma_spi3_tx.Instance = DMA2_Channel2;
        hdma_spi3_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;  // 内存到外设
        hdma_spi3_tx.Init.PeriphInc = DMA_PINC_DISABLE;      // 禁止外设地址递增
        hdma_spi3_tx.Init.MemInc = DMA_MINC_ENABLE;          // 允许内存地址递增
        hdma_spi3_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;  // 外设数据对齐：16 位
        hdma_spi3_tx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;     // 内存数据对齐：16 位
        hdma_spi3_tx.Init.Mode = DMA_CIRCULAR;               // 循环模式
        hdma_spi3_tx.Init.Priority = DMA_PRIORITY_HIGH;      // 高优先级
        HAL_DMA_Init(&hdma_spi3_tx);

        // 将 DMA 绑定到 SPI3 的 TX
        __HAL_LINKDMA(hi2s, hdmatx, hdma_spi3_tx);

        // 5. 配置 NVIC，启用中断
//        HAL_NVIC_SetPriority(DMA2_Channel2_IRQn, 0, 0);
//        HAL_NVIC_EnableIRQ(DMA2_Channel2_IRQn);
    }
}

void DMA2_Stream2_IRQHandler(void)
{
//    __HAL_DMA_DISABLE(hi2s3.hdmatx);                       //关闭DMA传输
//    __HAL_DMA_CLEAR_FLAG(hi2s3.hdmatx, DMA_FLAG_TCIF3_7);  //清除中断标记,换定时器时记得换flag
    __HAL_DMA_CLEAR_FLAG(hi2s3.hdmatx, __HAL_DMA_GET_GI_FLAG_INDEX(hi2s3.hdmatx));
//
//
//    __HAL_DMA_SET_COUNTER(TIM4_Handler.hdma[TIM_DMA_ID_CC3], 10);               //重新设置计数值
//    __HAL_DMA_ENABLE(TIM4_Handler.hdma[TIM_DMA_ID_CC3]);                        //开启DMA传输
}




// I²S3 初始化函数
void MX_I2S3_Init(void)
{
    // 配置 I²S 外设
    hi2s3.Instance = SPI3; // 使用 SPI3 实现 I²S3
    hi2s3.Init.Mode = I2S_MODE_MASTER_TX; // 主机发送模式
    hi2s3.Init.Standard = I2S_STANDARD_PHILIPS; // 使用 Philips I²S 标准
    hi2s3.Init.DataFormat = I2S_DATAFORMAT_24B; // 数据格式为 16 位
    hi2s3.Init.MCLKOutput = I2S_MCLKOUTPUT_DISABLE; // 禁用 MCLK 输出
    hi2s3.Init.AudioFreq = I2S_AUDIOFREQ_48K; // 音频采样率为 44.1 kHz
    hi2s3.Init.CPOL = I2S_CPOL_HIGH; // 时钟极性为低

    // 初始化 I²S3
    if (HAL_I2S_Init(&hi2s3) != HAL_OK)
    {
        // 初始化失败，进入错误处理
        Error_Handler();
    }
}

void I2S_Transmit(uint16_t *data, uint16_t size)
{
    if (HAL_I2S_Transmit(&hi2s3, data, size, HAL_MAX_DELAY) != HAL_OK)
    {
        // 传输失败，进入错误处理
        Error_Handler();
    }
}

void I2S3_Transmit_DMA(uint16_t *data, uint16_t size)
{
    int ret = HAL_I2S_Transmit_DMA(&hi2s3, data, size);
    if (ret != HAL_OK)
    {
        rt_kprintf("HAL_I2S_Transmit_DMA error:%d\r\n", ret);
        // DMA 传输失败
        Error_Handler();
    }
}

static int iis_init(void)
{
    MX_I2S3_Init();
    return 0;
}

INIT_BOARD_EXPORT(iis_init);
